package com.virtualparadigm.identity;

import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Properties;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

import com.virtualparadigm.hierarchy.LineageList;

public class ResourceLocator implements Serializable 
{
	// =========================================================
	// EXAMPLE USAGE
	// =========================================================
	/* 
		to create the following "role": resourcelocator://role.org.org.org/org3/org2/org1/role?name=admin
		
		LineageList<String> authorityLList = new LineageList<String>();
		authorityLList.pushParent("org");
		authorityLList.queueChild("supplier");
		
		LineageList<String> pathLList = new LineageList<String>();
		pathLList.pushParent("org1");
		pathLList.queueChild("org2");
		pathLList.queueChild("org3");
		
		Properties attributes = new Properties();
		attributes.put("name", "admin");
		ResourceLocator r1 = new ResourceLocator(authorityLList, pathLList, "role", attributes);	
	*/
	
	private static final long serialVersionUID = 1L; 
	public static String DEFAULT_SCHEME = "rl";
	
	private LineageList<ResourcePathElement> resourcePathElements; 
//	private URI uri; 
	private Properties attributes;	
	
	public ResourceLocator(LineageList<ResourcePathElement> resourcePathElements, Properties attributes) 
	{
		if(resourcePathElements != null)
		{
			ResourcePathElement deepestChildResourcePathElement = resourcePathElements.peekChild();
			if(deepestChildResourcePathElement.getName() == null || !deepestChildResourcePathElement.getName().equals(deepestChildResourcePathElement.getValuesString()))
			{
				throw new IllegalStateException("could not initialize resource identifier - deepest child name and value must match");
			}
		}
		URI uri = ResourceAddressParser.getResourceURI(DEFAULT_SCHEME, resourcePathElements, attributes);
		if(uri == null)
		{
			throw new IllegalStateException("could not initialize resource identifier");
		}
		this.resourcePathElements = resourcePathElements;
		this.attributes = attributes;
	}
	
	public ResourceLocator(String str) 
	{
		if(str != null && !str.startsWith(DEFAULT_SCHEME+":"))
		{
			throw new IllegalStateException("invalid scheme. could not initialize resource identifier");
		}
		
		try
		{
			URI uri = new URI(str);
			this.resourcePathElements = ResourceAddressParser.getResourcePathElementLineageList(uri.getAuthority(), uri.getPath());
			this.attributes = ResourceAddressParser.parseURIQuery(uri.getQuery());
		}
		catch(URISyntaxException urise)
		{
			urise.printStackTrace();
			throw new IllegalStateException("could not initialize resource identifier", urise);
		}
		
		if(this.resourcePathElements != null)
		{
			ResourcePathElement deepestChildResourcePathElement = this.resourcePathElements.peekChild();
			if(deepestChildResourcePathElement.getName() == null || !deepestChildResourcePathElement.getName().equals(deepestChildResourcePathElement.getValuesString()))
			{
				throw new IllegalStateException("could not initialize resource identifier - deepest child name and value must match");
			}
		}
	}
	
	public URI getURI()
	{
		return ResourceAddressParser.getResourceURI(DEFAULT_SCHEME, this.resourcePathElements, this.attributes);
	}
	
	public LineageList<ResourcePathElement> getResourcePathElements()
	{
		return resourcePathElements;
	}

	public Properties getAttributes()
	{
		return attributes;
	}

//	public String getNamespaceString()
//	{
//		String namespace = "";
//		if(this.uri != null)
//		{
//			namespace = this.uri.getAuthority();
//		}
//		return namespace;
//	}
//	
//	public String getPathString()
//	{
//		String path = "";
//		if(this.uri != null)
//		{
//			path = this.uri.getPath();
//		}
//		return path;
//	}
	
	public String getResourceType()
	{
		String resourceType = "";
		if(this.resourcePathElements != null)
		{
			ResourcePathElement resourcePathElement = this.resourcePathElements.peekChild();
			if(resourcePathElement != null)
			{
				resourceType = resourcePathElement.getName();
			}
		}
		return resourceType;
	}

//	public String getStringValue()
//	{
//		String str = null;
//		if(this.uri != null)
//		{
//			str = this.uri.toString();
//		}
//		return str;
//	}
	
	// ================================================
	// UTILITY METHODS
	// ================================================
	public String toString()
	{
		return this.getURI().toString();
	}
	
	public int hashCode()
	{
		HashCodeBuilder builder = new HashCodeBuilder(17,31);
	    builder.append(this.getResourcePathElements());
	    builder.append(this.getAttributes());
	    return builder.toHashCode();		
	}
	
	public boolean equals(Object obj)
	{
		if (obj == null)
		{
			return false;
		}
		if (obj == this)
		{
			return true;
		}
		if (obj.getClass() != getClass())
		{
			return false;
		}
		ResourceLocator that = (ResourceLocator)obj;
		EqualsBuilder builder = new EqualsBuilder();
	    builder.append(this.getResourcePathElements(), that.getResourcePathElements());
	    builder.append(this.getAttributes(), that.getAttributes());
		return builder.isEquals();
	}
	
	
	public static void main(String[] args)
	{
		try
		{
			ResourceLocator rl1 = new ResourceLocator(DEFAULT_SCHEME + "://bar.foo.com/c1/f1/b1?p1=a&p2=b");
			System.out.println(rl1);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
		try
		{
			ResourceLocator rl1 = new ResourceLocator(DEFAULT_SCHEME + "://bar.foo.com/c1/f1/bar?p1=a&p2=b");
			System.out.println(rl1);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
	}
	
	
}